from typing import List
from typing import Optional

from fastapi import Query, Body, APIRouter

from components.router import CenterRoute
from ioservice.institution import get_institution, insert_institution, update_institution, drop_institution_by_id, \
    get_institution_by_id, insert_institutions, search_institutions, bulk_update_institutions, sync_institutions_data, \
    crud_institutions_tree, crud_institutions_dept
from models.common import OID
from models.institution import Institution, InstitutionSearchModel, InstitutionUpdateModel
from task_utils.task_es import job_delete_institutions, job_task_institution_overview, job_task_update_dept_to_es, \
    job_task_update_activity_span, job_task_radar
from task_utils.task_jobs import job_update_ranking, job_update_ranking_v2

router = APIRouter(route_class=CenterRoute)


@router.post("/institution/search")
async def api_search_institution(context: InstitutionSearchModel):
    res = await search_institutions(context)
    job_update_ranking.apply_async()
    job_update_ranking_v2.apply_async()
    job_task_institution_overview.apply_async(queue='es')
    job_task_update_activity_span.apply_async(queue='es')
    job_task_radar.apply_async(queue='es')

    job_task_update_dept_to_es.apply_async(queue='es')

    return res


@router.get('/institution')
async def api_get_institution(name: Optional[str] = Query(None), province: Optional[str] = Query(None),
                              offset: int = Query(0, gte=0),
                              size: int = Query(20, le=100)):
    res = await get_institution(institution_name=name, province=province, skip=offset, limit=size)
    return res


@router.post('/institution/{institution_id}/info')
async def api_get_institution_by_id(institution_id: str,
                                    fields: Optional[List[str]] = Body(None, embed=True)):
    res = await get_institution_by_id(institution_id, projection=fields)
    return res


class APIInsertInstitution(Institution):
    institution_name: str
    parent_institution_name: Optional[str]


@router.put('/institution')
async def api_insert_institution(institution: APIInsertInstitution):
    institution_id = await insert_institution(institution)
    return {"id": institution_id}


@router.post('/institution')
async def api_update_institution(institution: InstitutionUpdateModel):
    institution_id = institution.id
    institution.fields_check(include=["id"], exclude=["ocode", "ocode_num", "create_time"])
    res = await update_institution(institution_id, Institution(**institution.dict(exclude_unset=True)))
    return res


@router.post('/institution/bulk')
async def api_update_institutions(institutions: List[InstitutionUpdateModel] = Body(..., embed=True)):
    for inst in institutions:
        inst.fields_check(include=["id"], exclude=["ocode", "ocode_num", "create_time"])
    res = await bulk_update_institutions(institutions)
    return res


@router.delete('/institution')
async def api_delete_institution(id: Optional[OID] = Body(..., embed=True)):
    res = await drop_institution_by_id(id)
    job_delete_institutions.apply_async(args=[[str(id)]], queue='es')
    return res


@router.put('/institution/bulk')
async def api_insert_institutions(institutions: List[APIInsertInstitution] = Body(..., embed=True)):
    res = await insert_institutions(institutions)
    return res


@router.post("/institution/sync")
async def api_update_institution_data(institutions: Optional[List[OID]] = Body([], embed=True)):
    status = await sync_institutions_data(institutions)
    return "success"


@router.get("/institution/tree")
async def branch_tree(by: bool = False):
    tree = await crud_institutions_tree(by)
    return tree


@router.get("/institution/dept", description="获得部门")
async def dept_tree(parent_name: Optional[str]):
    if not parent_name:
        return
    tree = await crud_institutions_dept(parent_name)
    return tree
